package cn.ltpcloud.common.utils;

import cn.ltpcloud.common.exception.QuicklyException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import static cn.ltpcloud.common.utils.JsonUtils.OBJECT_MAPPER;

/**
 * http 工具类
 *
 * @author jiejiebiezheyang
 * @since 2024-03-03 17:00
 */
public class HttpUtils {

    public final static OkHttpClient OK_HTTP_CLIENT = new OkHttpClient();

    public static final MediaType JSON = MediaType.get("application/json");

    /**
     * 发送get请求
     *
     * @param url    url
     * @param params 查询参数
     */
    public static String get(String url, Map<String, Object> params) {
        Request request = new Request.Builder()
                .url(url + encodeParams(params))
                .build();
        return execute(request);
    }

    /**
     * get 获取 JSON
     */
    public static ObjectNode getJSON(String url, Map<String, Object> params) {
        String str = get(url, params);
        try {
            return OBJECT_MAPPER.readValue(str, ObjectNode.class);
        } catch (JsonProcessingException e) {
            throw new QuicklyException(e.getMessage());
        }
    }

    /**
     * get 获取 JSON Array
     */
    public static ArrayNode getJSONArray(String url, Map<String, Object> params) {
        String str = get(url, params);
        try {
            return OBJECT_MAPPER.readValue(str, ArrayNode.class);
        } catch (JsonProcessingException e) {
            throw new QuicklyException(e.getMessage());
        }
    }

    /**
     * 发送post请求
     *
     * @param url    url
     * @param params 查询参数
     * @param body   请求体
     */
    public static String post(String url, Map<String, Object> params, Map<String, Object> body) {

        ObjectMapper objectMapper = new ObjectMapper();
        String json = null;
        try {
            json = objectMapper.writeValueAsString(body);
        } catch (JsonProcessingException e) {
            throw new QuicklyException(e.getMessage());
        }
        RequestBody requestBody = RequestBody.create(json, JSON);
        Request request = new Request.Builder()
                .url(url + encodeParams(params))
                .post(requestBody)
                .build();
        return execute(request);
    }

    /**
     * post 获取 JSON
     */
    public static ObjectNode postJSON(String url, Map<String, Object> params, Map<String, Object> body) {
        String str = post(url, params, body);
        try {
            return OBJECT_MAPPER.readValue(str, ObjectNode.class);
        } catch (JsonProcessingException e) {
            throw new QuicklyException(e.getMessage());
        }
    }

    /**
     * post 获取 JSON Array
     */
    public static ArrayNode postJSONArray(String url, Map<String, Object> params, Map<String, Object> body) {
        String str = post(url, params, body);
        try {
            return OBJECT_MAPPER.readValue(str, ArrayNode.class);
        } catch (JsonProcessingException e) {
            throw new QuicklyException(e.getMessage());
        }
    }

    /**
     * 执行请求
     */
    @NotNull
    private static String execute(Request request) {
        try (Response response = OK_HTTP_CLIENT.newCall(request).execute()) {
            if (response.body() != null) {
                return response.body().string();
            }
            return "";
        } catch (IOException e) {
            throw new QuicklyException(e.getMessage());
        }
    }

    /**
     * 参数编码
     *
     * @param params 查询参数
     */
    public static String encodeParams(Map<String, Object> params) {
        if (params == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append("?");
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value == null) continue;

            List<String> values = (value instanceof List<?>) ?
                    (List<String>) value :
                    Collections.singletonList(String.valueOf(value));

            for (String item : values) {
                if (item == null || item.isEmpty()) continue;
                if (sb.length() > 1) {
                    sb.append("&");
                }
                sb.append(URLEncoder.encode(key, StandardCharsets.UTF_8));
                sb.append("=");
                sb.append(URLEncoder.encode(item, StandardCharsets.UTF_8));
            }
        }
        return sb.toString();
    }

}
